/*************************************************
Author: will
Date: 10/26/2012
Description:
Notes: 
*************************************************/

#ifndef __CMonsterConfig_h__
#define __CMonsterConfig_h__

#include "CTHashObjectMgr.h"
#include "CTArray.h"
#include "commclass.h"
#include "commerrno.h"

#include "pb_cfg_monster.pb.h"

//////////////////////////////////////////////////////////////////////////
class CMonsterFirstKillBonusConfigData
{
public:
    CMonsterFirstKillBonusConfigData() 
        :_bHasConfig(false), _usMonsterGroupLevel(0), _uiHunli(0)
    {
    }

    virtual ~CMonsterFirstKillBonusConfigData() 
    {
    }

public:
    bool _bHasConfig;
    unsigned short _usMonsterGroupLevel;

    unsigned int _uiHunli;
};


class CMonsterFirstKillBonusConfig
{
public:
    CMonsterFirstKillBonusConfig() 
    {
    }

    virtual ~CMonsterFirstKillBonusConfig() 
    {
    }

    int AddConfig(CMonsterFirstKillBonusConfigData& stConfigData)
    {
        if (stConfigData._usMonsterGroupLevel <= 0 || stConfigData._usMonsterGroupLevel > MAX_MONSTER_FIRST_KILL_BONUS_CONFIG_COUNT)
        {
            CT_ERROR(("invalid monster group level %d", stConfigData._usMonsterGroupLevel));
            return RET_SYSTEM_FAIL;
        }

        if (_astFirstKillBonusConfigData[stConfigData._usMonsterGroupLevel]._bHasConfig)
        {
            CT_ERROR(("add duplicate kill bonus config , group level %d", stConfigData._usMonsterGroupLevel));
            return RET_SYSTEM_FAIL;
        }

        _astFirstKillBonusConfigData[stConfigData._usMonsterGroupLevel] = stConfigData;
        _astFirstKillBonusConfigData[stConfigData._usMonsterGroupLevel]._bHasConfig = true;
        return 0;
    }

    int GetConfig(unsigned short usMonsterGroupLevel, CMonsterFirstKillBonusConfigData& stConfigData)
    {
        if (usMonsterGroupLevel <= 0 || usMonsterGroupLevel > MAX_MONSTER_FIRST_KILL_BONUS_CONFIG_COUNT)
        {
            return ERROR_MONSTER_NO_FIRST_KILL_BONUS_CONFIG;
        }

        if (!_astFirstKillBonusConfigData[usMonsterGroupLevel]._bHasConfig)
        {
            return ERROR_MONSTER_NO_FIRST_KILL_BONUS_CONFIG;
        }

        stConfigData = _astFirstKillBonusConfigData[usMonsterGroupLevel];
        return 0;
    }

private:
    CTLib::CTArray<CMonsterFirstKillBonusConfigData, MAX_MONSTER_FIRST_KILL_BONUS_CONFIG_COUNT + 1> _astFirstKillBonusConfigData;
};


//////////////////////////////////////////////////////////////////////////
class CMonsterKillBonusConfigData
{
public:
	CMonsterKillBonusConfigData() 
        :_bHasConfig(false), _usMonsterGroupLevel(0), _uiExp(0), _uiSilver(0), _uiLilian(0)
    {
	}

	virtual ~CMonsterKillBonusConfigData() 
    {
	}

public:
	bool _bHasConfig;
    unsigned short _usMonsterGroupLevel;

    unsigned int _uiExp;
    unsigned int _uiSilver;
    unsigned int _uiLilian;
};

class CMonsterKillBonusConfig
{
public:
	CMonsterKillBonusConfig() 
    {
	}

	virtual ~CMonsterKillBonusConfig() 
    {
	}

    int AddConfig(CMonsterKillBonusConfigData& stConfigData)
    {
        if (stConfigData._usMonsterGroupLevel <= 0 || stConfigData._usMonsterGroupLevel > MAX_MONSTER_KILL_BONUS_CONFIG_COUNT)
        {
            CT_ERROR(("invalid monster group level %d", stConfigData._usMonsterGroupLevel));
            return RET_SYSTEM_FAIL;
        }

        if (_astKillBonusConfigData[stConfigData._usMonsterGroupLevel]._bHasConfig)
        {
            CT_ERROR(("add duplicate kill bonus config , group level %d", stConfigData._usMonsterGroupLevel));
            return RET_SYSTEM_FAIL;
        }

        _astKillBonusConfigData[stConfigData._usMonsterGroupLevel] = stConfigData;
        _astKillBonusConfigData[stConfigData._usMonsterGroupLevel]._bHasConfig = true;
        return 0;
    }

    int GetConfig(unsigned short usMonsterGroupLevel, CMonsterKillBonusConfigData& stConfigData)
    {
        if (usMonsterGroupLevel <= 0 || usMonsterGroupLevel > MAX_MONSTER_KILL_BONUS_CONFIG_COUNT)
        {
            return ERROR_MONSTER_NO_KILL_BONUS_CONFIG;
        }

        if (!_astKillBonusConfigData[usMonsterGroupLevel]._bHasConfig)
        {
            return ERROR_MONSTER_NO_KILL_BONUS_CONFIG;
        }

        stConfigData = _astKillBonusConfigData[usMonsterGroupLevel];
        return 0;
    }

private:
    CTLib::CTArray<CMonsterKillBonusConfigData, MAX_MONSTER_KILL_BONUS_CONFIG_COUNT + 1> _astKillBonusConfigData;
};

//////////////////////////////////////////////////////////////////////////
class CMonsterTypeConfigData
{
public:
	CMonsterTypeConfigData() 
        :_usMonsterType(0),
        _uiHpAdjust(0),
        _uiPhyAtkAdjust(0), 
        _uiPhyDefAdjust(0),
        _uiMagAtkAdjust(0),
        _uiMagDefAdjust(0),
        _uiEarthAtkAdjust(0),
        _uiWarterAtkAdjust(0),
        _uiFireAtkAdjust(0),
        _uiWindAtkAdjust(0),
        _uiHitLevelAdjust(0),
        _uiDodgeLevelAdjust(0),
        _uiDoubleLevelAdjust(0),
        _uiAntiDoubleLevelAdjust(0),
        _uiCritLevelAdjust(0),
        _uiBlockLevelAdjust(0),
        _uiAntiBlockLevelAdjust(0),
        _uiTurnOrderValueAdjust(0),
        _uiInitAngerAdjust(0),
        _uiAngerRecoverRateAdjust(0),
        _uiInitCourageAdjust(0),
        _uiCourageRecoverRateAdjust(0),
        _uiFightBackRateAdjust(0),
        _uiImmuneInjuryRateAdjust(0),
        _uiReactInjuryRateAdjust(0),
        _uiPenetrateRateAdjust(0),
        _uiTreatmentRateAdjust(0)
    {
	}

	virtual ~CMonsterTypeConfigData() 
    {
	}

public:
	unsigned short _usMonsterType;
    
    unsigned int _uiHpAdjust;               //生命值修正系数
    int            _iHPBasePos;             //生命值修正系数下标（对应怪物属性表中的生命值 CMonsterAttrConfigData::_auiHP）

    unsigned int _uiPhyAtkAdjust;           //物理攻击修正系数
    unsigned int _uiPhyDefAdjust;           //物理防御修正系数
    unsigned int _uiMagAtkAdjust;           //魔法攻击修正系数
    unsigned int _uiMagDefAdjust;           //魔法防御修正系数

    unsigned int _uiEarthAtkAdjust;         //地攻修正系数
    unsigned int _uiWarterAtkAdjust;        //水攻修正系数
    unsigned int _uiFireAtkAdjust;          //火攻修正系数
    unsigned int _uiWindAtkAdjust;          //风攻修正系数

    unsigned int _uiHitLevelAdjust;             //命中修正系数
    unsigned int _uiDodgeLevelAdjust;           //闪避修正系数
    unsigned int _uiDoubleLevelAdjust;          //暴击修正系数
    unsigned int _uiAntiDoubleLevelAdjust;      //抗暴击修正系数
    unsigned int _uiCritLevelAdjust;            //必杀修正系数
    unsigned int _uiBlockLevelAdjust;           //格挡修正系数
    unsigned int _uiAntiBlockLevelAdjust;       //破击修正系数

    unsigned int _uiTurnOrderValueAdjust;       //出手速度修正系数
    unsigned int _uiInitAngerAdjust;            //怒气修正系数
    unsigned int _uiAngerRecoverRateAdjust;     //怒气恢复速度修正系数
    unsigned int _uiInitCourageAdjust;          //勇气修正系数
    unsigned int _uiCourageRecoverRateAdjust;   //勇气恢复速度修正系数
    unsigned int _uiFightBackRateAdjust;        //反击机率修正系数
    unsigned int _uiImmuneInjuryRateAdjust;     //免伤机率修正系数
    unsigned int _uiReactInjuryRateAdjust;      //反伤机率修正系数
    unsigned int _uiPenetrateRateAdjust;        //穿透机率修正系数
    unsigned int _uiTreatmentRateAdjust;        //痊愈机率修正系数
};

class CMonsterTypeConfig
{
public:
    typedef CTLib::CTHashObjectMgr<unsigned short, CMonsterTypeConfigData> T_MONSTER_TYPE_CONFIG_HASH;

	CMonsterTypeConfig() 
    {
	}

	virtual ~CMonsterTypeConfig() 
    {
	}

    static size_t CountSize()
    {
        return T_MONSTER_TYPE_CONFIG_HASH::CountSize(MAX_MONSTER_TYPE_CONFIG_COUNT);
    }

    int Init(const char * sBuff)
    {
        return _stMonsterTypeConfigHash.Init(sBuff, MAX_MONSTER_TYPE_CONFIG_COUNT);
    }

    int AddConfig(CMonsterTypeConfigData& stConfigData)
    {
        int iIndex = _stMonsterTypeConfigHash.HashFind(stConfigData._usMonsterType);
        if (iIndex >= 0)
        {
            CT_ERROR(("find duplicate monster type %d", stConfigData._usMonsterType));
            return RET_SYSTEM_FAIL;
        }

        iIndex = _stMonsterTypeConfigHash.HashAlloc(stConfigData._usMonsterType);
        if (iIndex < 0)
        {
            CT_ERROR(("monster type is full"));
            return RET_SYSTEM_FAIL;
        }

        _stMonsterTypeConfigHash[iIndex] = stConfigData;
        return 0;
    }

    int GetConfig(unsigned short usMonsterType, CMonsterTypeConfigData& stConfigData)
    {
        int iIndex = _stMonsterTypeConfigHash.HashFind(usMonsterType);
        if (iIndex < 0)
        {
            return ERROR_MONSTER_NO_TYPE_CONFIG;
        }

        stConfigData = _stMonsterTypeConfigHash[iIndex];
        return 0;
    }

private:
	T_MONSTER_TYPE_CONFIG_HASH _stMonsterTypeConfigHash;
};

//////////////////////////////////////////////////////////////////////////

class CMonsterAttrConfigData
{
public:
	CMonsterAttrConfigData()
        :_bHasConfig(false)
    {
        _auiHP.m_iUsedCount = _auiHP.GetCount();
        for (int i = 0; i < _auiHP.Size(); ++i)
        {
            _auiHP[i] = 0;
        }
	}

	virtual ~CMonsterAttrConfigData() 
    {
	}

    unsigned int GetHP(int iPos)
    {
        if (iPos < 0 || iPos >= _auiHP.Size()
            || _auiHP[iPos] == 0)
        {
            return _auiHP[0];
        }

        return _auiHP[iPos];
    }

public:
    bool _bHasConfig;
	unsigned short _usLevel;

    CTArray<unsigned int, 3> _auiHP;    //生命值
    unsigned int   _uiHP;               //修正后的血量
    unsigned int _uiPhyAtk;             //物理攻击
    unsigned int _uiPhyDef;             //物理防御
    unsigned int _uiMagAtk;             //魔法攻击
    unsigned int _uiMagDef;             //魔法防御

    unsigned int _uiEarthAtk;           //地攻
    unsigned int _uiWaterAtk;           //水攻
    unsigned int _uiFireAtk;            //火攻
    unsigned int _uiWindAtk;            //风攻
    
    unsigned int _uiHitLevel;           //命中等级
    unsigned int _uiDodgeLevel;         //闪避等级
    unsigned int _uiDoubleLevel;        //暴击等级
    unsigned int _uiAntiDoubleLevel;    //抗暴击等级
    unsigned int _uiCritLevel;          //必杀等级
    unsigned int _uiBlockLevel;         //格挡等级
    unsigned int _uiAntiBlockLevel;     //破击等级

    unsigned int _uiTurnOrderValue;     //出手速度(先手值)
    unsigned int _uiInitAnger;          //初始怒气
    unsigned int _uiAngerRecoverRate;   //怒气恢复速度
    unsigned int _uiInitCourage;        //初始勇气
    unsigned int _uiCourageRecoverRate; //勇气恢复速度
    unsigned int _uiImmuneInjuryRate;   //免伤机率
    unsigned int _uiReactInjuryRate;    //反伤机率
    unsigned int _uiPenetrateRate;      //穿透机率
    unsigned int _uiTreatmentRate;      //痊愈机率
    unsigned int _uiFightBackRate;      //反击机率
};

class CMonsterAttrConfig
{
public:
	CMonsterAttrConfig() 
    {
	}

	virtual ~CMonsterAttrConfig() 
    {
	}

    int AddConfig(CMonsterAttrConfigData& stConfigData)
    {
        if (stConfigData._usLevel <= 0 || stConfigData._usLevel > MAX_MONSTER_ATTR_CONFIG_COUNT)
        {
            CT_ERROR(("invalid monster attr level %d", stConfigData._usLevel));
            return RET_SYSTEM_FAIL;
        }

        if (_astMonsterAttrConfigDatas[stConfigData._usLevel]._bHasConfig)
        {
            CT_ERROR(("add duplicate monster attr config , level %d", stConfigData._usLevel));
            return RET_SYSTEM_FAIL;
        }

        _astMonsterAttrConfigDatas[stConfigData._usLevel] = stConfigData;
        _astMonsterAttrConfigDatas[stConfigData._usLevel]._bHasConfig = true;
        return 0;
    }

    int GetConfig(unsigned short usLevel, CMonsterAttrConfigData& stConfigData)
    {
        if (usLevel <= 0 || usLevel > MAX_MATERIAL_CONFIG_COUNT)
        {
            return ERROR_MONSTER_NO_ATTR_CONFIG;
        }

        if (!_astMonsterAttrConfigDatas[usLevel]._bHasConfig)
        {
            return ERROR_MONSTER_NO_ATTR_CONFIG;
        }

        stConfigData = _astMonsterAttrConfigDatas[usLevel];
        return 0;
    }

private:
    CTLib::CTArray<CMonsterAttrConfigData, MAX_MONSTER_ATTR_CONFIG_COUNT + 1> _astMonsterAttrConfigDatas;
};

//////////////////////////////////////////////////////////////////////////
class CMonsterConfigData
{
public:
	CMonsterConfigData() 
    {
	}

	virtual ~CMonsterConfigData() 
    {
	}

public:
    unsigned char _ucCareer;
	unsigned int _uiMonsterID;

    unsigned short _usDefaultLevel;
    unsigned short _usMonsterType;
    unsigned int   _uiNormalSkillID;
    unsigned int   _uiAcademySkillID;
    unsigned int   _uiMagicSkillID;
    int            _iStatusGroupID;
    CMonsterAttrConfigData    _stMonsterDefaultAttr;
};

class CMonsterConfig
{
public:
    typedef CTLib::CTHashObjectMgr<unsigned int, CMonsterConfigData> T_MONSTER_CONFIG_HASH;

	CMonsterConfig() 
    {
	}

	virtual ~CMonsterConfig() 
    {
	}

    static size_t CountSize()
    {
        return T_MONSTER_CONFIG_HASH::CountSize(MAX_MONSTER_CONFIG_COUNT);
    }

    int Init(const char* sBuff)
    {
        return _stMonsterConfigHash.Init(sBuff, MAX_MONSTER_CONFIG_COUNT);
    }

    int AddConfig(CMonsterConfigData& stConfigData)
    {
        int iIndex = _stMonsterConfigHash.HashFind(stConfigData._uiMonsterID);
        if (iIndex >= 0)
        {
            CT_ERROR(("add duplicate monster id %u", stConfigData._uiMonsterID));
            return RET_SYSTEM_FAIL;
        }

        iIndex = _stMonsterConfigHash.HashAlloc(stConfigData._uiMonsterID);
        if (iIndex < 0)
        {
            CT_ERROR(("monster config hash full, id %u", stConfigData._uiMonsterID));
            return RET_SYSTEM_FAIL;
        }

        CT_TRACE(("add monster id %d", stConfigData._uiMonsterID));
        _stMonsterConfigHash[iIndex] = stConfigData;
        return 0;
    }

    int FindConfig(unsigned int uiMonsterID)
    {
        return _stMonsterConfigHash.HashFind(uiMonsterID);
    }

    CMonsterConfigData& GetConfig(int iIndex)
    {
        return _stMonsterConfigHash[iIndex];
    }

    int GetConfig(unsigned int uiMonsterID, CMonsterConfigData& stConfigData)
    {
        int iIndex = _stMonsterConfigHash.HashFind(uiMonsterID);
        if (iIndex < 0)
        {
            CT_ERROR(("monster id %d", uiMonsterID));
            return ERROR_MONSTER_NO_MONSTER_CONFIG;
        }

        stConfigData = _stMonsterConfigHash[iIndex];
        return 0;
    }

private:
	T_MONSTER_CONFIG_HASH _stMonsterConfigHash;
};

//////////////////////////////////////////////////////////////////////////

class CMonsterGroupMember
{
public:
	CMonsterGroupMember() 
    {
	}

	virtual ~CMonsterGroupMember() 
    {
	}

public:
    unsigned int    _uiMonsterID;   //怪物ID
    unsigned short  _usPos;         //怪物位置
    unsigned char   _ucTurnOrder;   //怪物出手顺序

    CMonsterConfigData _stMonster;  //怪物详情
};

class CMonsterGroupConfigData
{
public:
	CMonsterGroupConfigData() 
    {
	}

	virtual ~CMonsterGroupConfigData() 
    {
	}

public:
	unsigned int _uiMonsterGroupID;

    unsigned short _usDefaultLevel;
    unsigned char  _ucIsBoss;
    CTLib::CTArray<CMonsterGroupMember, MAX_MONSTER_MEMBER_PER_GROUP> _astMonsters;
    bool _bHasFirstKillBonus;
};

class CMonsterGroupConfig
{
public:
    typedef CTLib::CTHashObjectMgr<unsigned int, CMonsterGroupConfigData> T_MONSTER_GROUP_CONFIG_HASH;
	CMonsterGroupConfig() 
    {
	}

	virtual ~CMonsterGroupConfig() 
    {
	}

    static int CountSize()
    {
        return T_MONSTER_GROUP_CONFIG_HASH::CountSize(MAX_MONSTER_GROUP_CONFIG_COUNT);
    }

    int Init(const char *sBuff)
    {
        return _stMonsterGroupConfigHash.Init(sBuff, MAX_MONSTER_GROUP_CONFIG_COUNT);
    }

    int AddConfig(CMonsterGroupConfigData& stConfigData);

    int GetConfig(unsigned int uiMonsterGroupID, CMonsterGroupConfigData& stConfigData)
    {
        int iIndex = _stMonsterGroupConfigHash.HashFind(uiMonsterGroupID);
        if (iIndex < 0)
        {
            return ERROR_MONSTER_NO_MONSTER_GROUP_CONFIG;
        }

        stConfigData = _stMonsterGroupConfigHash[iIndex];
        return 0;
    }

    int FindConfig(unsigned int uiMonsterGroupID)
    {
        int iIndex = _stMonsterGroupConfigHash.HashFind(uiMonsterGroupID);
        if (iIndex >= 0)
        {
            return iIndex;
        }

        return -1;
    }

private:
	T_MONSTER_GROUP_CONFIG_HASH _stMonsterGroupConfigHash;
};

#endif // __CMonsterConfig_h__

